/*
 * OpenParts
 * A dynamic-loading components framework for GWT
 * Copyright (C) 2011 Christophe Bouthier  [chris{AT}binary-gastronome{DOT}fr]
 *
 * This work is partially based on work I have done at INRIA (http://www.inria.fr) 
 * in the context of the Qualipso European Project (http://qualipso.org/),
 * The work done at INRIA is Copyright (C) 2006-2011 INRIA
 *
 * This work is distributed under the LGPL version 3
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License version 3
 * as published by the Free Software Foundation. See the GNU
 * Lesser General Public License in LGPL.txt for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package fr.openparts.OpenParts.test.gwt.tests;

import com.google.gwt.junit.client.GWTTestCase;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.RootPanel;

import fr.openparts.OpenParts.client.OPMessageFromEmbeddedViewHandler;
import fr.openparts.OpenParts.client.OPMessagesDispatcher;
import fr.openparts.OpenParts.client.OPParams;
import fr.openparts.OpenParts.client.OPParamsJS;
import fr.openparts.OpenParts.client.OPViewProxy;

/**
 * GWT tests for OPViewProxy.
 * 
 * @author Christophe Bouthier [chris{AT}binary-gastronome{DOT}fr]
 * @creation.date 18 January 2011
 */
public class OPViewProxyTestGwt extends GWTTestCase {

    private static final String SLOT_ID = "dummySlotId_viewProxy";
    private static final String MESSAGE = "dummyMessage";
    private static final String PARAM_NAME = "dummyParamName";
    private static final String PARAM_VALUE = "dummyParamValue";

    private OPViewProxy proxy;
    private OPMessagesDispatcher dispatcher;
    private DummyMessageFromEmbeddedViewHandler handler;
    private OPParams params;
    private OPParamsJS paramsjs;

    /**
     * Return the name of the tested GWT Module.
     * 
     * @see com.google.gwt.junit.client.GWTTestCase#getModuleName()
     */
    @Override
    public final String getModuleName() {
        return "fr.openparts.OpenParts.test.gwt.TestOpenParts";
    }

    /**
     * Called at the start of each test to set up the service.
     * 
     * @see com.google.gwt.junit.client.GWTTestCase#gwtSetUp()
     */
    @Override
    protected void gwtSetUp() throws Exception {
        super.gwtSetUp();
        proxy = new OPViewProxy(SLOT_ID);
        dispatcher = OPMessagesDispatcher.dispatcherFactory(SLOT_ID);
        dispatcher.registerViewProxy(proxy);
        handler = new DummyMessageFromEmbeddedViewHandler();
        params = new OPParams(PARAM_NAME, PARAM_VALUE);
        paramsjs = OPParamsJS.buildFromOPParams(params);
    }

    /**
     * Test constructor.
     */
    public final void testConstructor() {
        assertNotNull("View proxy shouldn't be null", proxy);
        assertTrue("Proxy should be registered in dispatcher", dispatcher.isMessageFromEmbeddedViewHandlerCallbackRegistered());
        assertFalse("Container slot callback should not be registered in dispatcher", dispatcher.isMessageFromContainerSlotHandlerCallbackRegistered());
    }

    /**
     * Test constructor passing a null slot id. Should raise an assertion error.
     */
    public final void testConstructorWithNullSlotId() {
        if (assertionsAreEnabled()) {
            try {
                proxy = new OPViewProxy(null);
                fail("OPViewProxy should raise an assertion error when constructed with a with a null slot id.");
            } catch (AssertionError e) {
                assertTrue("Error should be an AssertionError", e instanceof AssertionError);
            }
        }
    }

    /**
     * Test constructor passing an empty slot id. Should raise an assertion error.
     */
    public final void testConstructorWithEmptySlotId() {
        if (assertionsAreEnabled()) {
            try {
                proxy = new OPViewProxy("");
                fail("OPViewProxy should raise an assertion error when constructed with a with an empty slot id.");
            } catch (AssertionError e) {
                assertTrue("Error should be an AssertionError", e instanceof AssertionError);
            }
        }
    }
    
    /**
     * Test adding a message handler. Should get true.
     */
    public final void testAddingMessageHandler() {
        assertTrue("View proxy should return true when registering an handler for the first time", proxy.addMessageHandler(handler));
    }

    /**
     * Test adding a null message handler. Should raise an assertion error.
     */
    public final void testAddingNullMessageHandler() {
        if (assertionsAreEnabled()) {
            try {
                proxy.addMessageHandler(null);
                fail("OPViewProxy should raise an assertion error when adding a null message handler.");
            } catch (AssertionError e) {
                assertTrue("Error should be an AssertionError", e instanceof AssertionError);
            }
        }
    }

    /**
     * Test adding two times the same message handler. First should return true, second should return false.
     */
    public final void testAddingMessageHandlerTwoTimes() {
        assertTrue("View proxy should return true when registering an handler for the first time", proxy.addMessageHandler(handler));
        assertFalse("View proxy should return false when registering an handler for the second time", proxy.addMessageHandler(handler));
    }

    /**
     * Test removing a registered message handler. Should return true.
     */
    public final void testRemovingMessageHandlerRegistered() {
        proxy.addMessageHandler(handler);
        assertTrue("View proxy should return true when removing registered message handler", proxy.removeMessageHandler(handler));
    }

    /**
     * Test removing an unregistered message handler. Should return false.
     */
    public final void testRemovingMessageHandlerUnregistered() {
        assertFalse("View proxy should return false when removing unregistered message handler",
                proxy.removeMessageHandler(new DummyMessageFromEmbeddedViewHandler()));
    }

    /**
     * Test removing a null message handler. Should raise an assertion error.
     */
    public final void testRemovingMessageHandlerNull() {
        if (assertionsAreEnabled()) {
            try {
                proxy.removeMessageHandler(null);
                fail("OPViewProxy should raise an assertion error when removing a null message handler.");
            } catch (AssertionError e) {
                assertTrue("Error should be an AssertionError", e instanceof AssertionError);
            }
        }
    }

    /**
     * Test removing two times the same message handler. First should return true, second should return false.
     */
    public final void testRemovingMessageHandlerTwoTimes() {
        assertTrue("View proxy should return true when registering an handler for the first time", proxy.addMessageHandler(handler));
        assertFalse("View proxy should return false when registering an handler for the second time", proxy.addMessageHandler(handler));
        assertTrue("View proxy should return true when removing message handler the first time", proxy.removeMessageHandler(handler));
        assertFalse("View proxy should return false when removing message handler the second time", proxy.removeMessageHandler(handler));
    }

    /**
     * Test dispatching message to handlers. Should get back the message and its params.
     */
    public final void testDispatchMessageWithParams() {
        proxy.addMessageHandler(handler);

        assertEquals("Handler should not have been called yet", 0, handler.counterOfTimeCalled);

        dispatcher.dispatchMessageToContainerSlot(MESSAGE, paramsjs);

        assertEquals("Handler should have been called now, and only once", 1, handler.counterOfTimeCalled);
        assertEquals("Handler should get message passed", MESSAGE, handler.message);
        assertNotNull("Handler should get some params passed", handler.params);
        assertEquals("passed params should contains one element", 1, handler.params.size());
    }

    /**
     * Test dispatching message with a null message. Should raise an assertion error.
     */
    public final void testDispatchingMessageWithNullMessage() {
        if (assertionsAreEnabled()) {
            try {
                dispatcher.dispatchMessageToContainerSlot(null, paramsjs);
                fail("OPViewProxy should raise an assertion error when dispatching a message with a null message.");
            } catch (AssertionError e) {
                assertTrue("Error should be an AssertionError", e instanceof AssertionError);
            }
        }
    }

    /**
     * Test dispatching message with null params. Should get back the message and a null params.
     */
    public final void testDispatchingMessageWithNullParams() {
        proxy.addMessageHandler(handler);

        assertEquals("Handler should not have been called yet", 0, handler.counterOfTimeCalled);

        dispatcher.dispatchMessageToContainerSlot(MESSAGE, null);

        assertEquals("Handler should have been called now, and only once", 1, handler.counterOfTimeCalled);
        assertEquals("Handler should get message passed", MESSAGE, handler.message);
        assertEquals("Handler should get null params", null, handler.params);
    }

    /**
     * Test dispatching message with empty params. Should get back the message and an empty params.
     */
    public final void testDispatchingMessageWithEmptyParams() {
        proxy.addMessageHandler(handler);

        assertEquals("Handler should not have been called yet", 0, handler.counterOfTimeCalled);

        dispatcher.dispatchMessageToContainerSlot(MESSAGE, OPParamsJS.buildFromOPParams(new OPParams()));

        assertEquals("Handler should have been called now, and only once", 1, handler.counterOfTimeCalled);
        assertEquals("Handler should get message passed", MESSAGE, handler.message);
        assertNotNull("Handler should get some params passed", handler.params);
        assertEquals("Handler should get empty params", 0, handler.params.size());
    }

    /**
     * Test dispatching message to two handlers. The two handlers should get back passed messages and params, and be called exactly once each.
     */
    public final void testDispatchingMessageToTwoHandlers() {
        DummyMessageFromEmbeddedViewHandler handler2 = new DummyMessageFromEmbeddedViewHandler();

        proxy.addMessageHandler(handler);
        proxy.addMessageHandler(handler2);

        assertEquals("Handler should not have been called yet", 0, handler.counterOfTimeCalled);

        dispatcher.dispatchMessageToContainerSlot(MESSAGE, paramsjs);

        assertEquals("Handler should have been called exactly once", 1, handler.counterOfTimeCalled);
        assertEquals("Handler should get message passed", MESSAGE, handler.message);
        assertNotNull("Handler should get some params passed", handler.params);
        assertEquals("passed params should contains one element", 1, handler.params.size());

        assertEquals("Handler 2 should have been called exactly once", 1, handler2.counterOfTimeCalled);
        assertEquals("Handler 2 should get message passed", MESSAGE, handler2.message);
        assertNotNull("Handler 2 should get some params passed", handler2.params);
        assertEquals("passed params should contains one element", 1, handler2.params.size());
    }

    /**
     * Test dispatching message to a handler that tried to register 2 times. Should be called only once.
     */
    public final void testDispatchingMessageToOneHandlerRegisteredTwoTimes() {
        proxy.addMessageHandler(handler);
        proxy.addMessageHandler(handler);

        assertEquals("Handler should not have been called yet", 0, handler.counterOfTimeCalled);

        dispatcher.dispatchMessageToContainerSlot(MESSAGE, paramsjs);

        assertEquals("Handler should have been called exactly once", 1, handler.counterOfTimeCalled);
    }

    /**
     * Test dispatching message to a handler that registered then unregistered. Should not be called at all.
     */
    public final void testDispatchingMessageToOneHandlerUnregistered() {
        proxy.addMessageHandler(handler);
        proxy.removeMessageHandler(handler);

        assertEquals("Handler should not have been called yet", 0, handler.counterOfTimeCalled);

        dispatcher.dispatchMessageToContainerSlot(MESSAGE, paramsjs);

        assertEquals("Handler should not have been called at all", 0, handler.counterOfTimeCalled);
    }
    
    /**
     * Test informing handler that embedded view is attached.
     */
    public final void testEmbeddedViewAttach() {
        proxy.addMessageHandler(handler);

        assertEquals("Handler should not have been called yet", 0, handler.counterOfOnAttachCalled);

        dispatcher.onEmbeddedViewAttach();

        assertEquals("Handler should have been called now, and only once", 1, handler.counterOfOnAttachCalled);
    }

    /**
     * Test informing two handlers that embedded view is attached. The two handlers should be called exactly once each.
     */
    public final void testEmbeddedViewAttachTwoHandlers() {
        DummyMessageFromEmbeddedViewHandler handler2 = new DummyMessageFromEmbeddedViewHandler();

        proxy.addMessageHandler(handler);
        proxy.addMessageHandler(handler2);

        assertEquals("Handler should not have been called yet", 0, handler.counterOfOnAttachCalled);

        dispatcher.onEmbeddedViewAttach();

        assertEquals("Handler should have been called exactly once", 1, handler.counterOfOnAttachCalled);
        assertEquals("Handler 2 should have been called exactly once", 1, handler2.counterOfOnAttachCalled);
    }

    /**
     * Test informing about embedded view attachment a handler that tried to register 2 times. Should be called only once.
     */
    public final void testEmbeddedViewAttachOneHandlerRegisteredTwoTimes() {
        proxy.addMessageHandler(handler);
        proxy.addMessageHandler(handler);

        assertEquals("Handler should not have been called yet", 0, handler.counterOfOnAttachCalled);

        dispatcher.onEmbeddedViewAttach();

        assertEquals("Handler should have been called exactly once", 1, handler.counterOfOnAttachCalled);
    }

    /**
     * Test informing about embedded view attachment a handler that registered then unregistered. Should not be called at all.
     */
    public final void testEmbeddedViewAttachOneHandlerUnregistered() {
        proxy.addMessageHandler(handler);
        proxy.removeMessageHandler(handler);

        assertEquals("Handler should not have been called yet", 0, handler.counterOfOnAttachCalled);

        dispatcher.onEmbeddedViewAttach();

        assertEquals("Handler should not have been called at all", 0, handler.counterOfOnAttachCalled);
    }
    
    /**
     * Test checking that the view proxy is attached to a real view. Should return true;
     */
    public final void testProxyAttachedToRealView() {
        assertFalse("Proxy should not be attached yet to a real view", proxy.isProxyAttachedToRealView());

        final Element element = DOM.createDiv();
        element.setId(SLOT_ID);
        RootPanel.getBodyElement().appendChild(element);
        dispatcher.attachDispatcherOnElement(element);
        registerDummyProxyInDispatcher(dispatcher);

        assertTrue("Proxy should be attached now to a real view", proxy.isProxyAttachedToRealView());
        
        RootPanel.getBodyElement().removeChild(element);
    }

    /**
     * Test setting a view style name. To prove that a real message was send, we test for assertion error about missing scheduler (as we're in a test environment).
     */
    public final void testSetStyleName() {
        final Element element = DOM.createDiv();
        element.setId(SLOT_ID);
        RootPanel.getBodyElement().appendChild(element);
        dispatcher.attachDispatcherOnElement(element);
        registerDummyProxyInDispatcher(dispatcher);
        
        if (assertionsAreEnabled()) {
            try {
                proxy.setStyleName("test");
                fail("proxy didn't try to send a real proxy command");
            } catch (AssertionError e) {
                assertTrue("Error should be about missing scheduler", e.getMessage().contains("scheduler"));
            }
        }

        RootPanel.getBodyElement().removeChild(element);
    }
    
    /**
     * Test setting a view style name when no real view is attached. Nothing should happens, no real message should be sent.
     */
    public final void testSetStyleNameWithNoRealViewAttached() {
        assertFalse("Proxy should not be attached yet to a real view", proxy.isProxyAttachedToRealView());

        if (assertionsAreEnabled()) {
            try {
                proxy.setStyleName("test");
                assertTrue(true);
            } catch (AssertionError e) {
                fail("proxy did try to send a real proxy command");
            }
        }
    }
    
    /**
     * Test trying to set a null style name on the view . Should raise an assertion error.
     */
    public final void testSetStyleNameWithNullStyle() {
        if (assertionsAreEnabled()) {
            try {
                proxy.setStyleName(null);
                fail("OPViewProxy should raise an assertion error when setting a null style name.");
            } catch (AssertionError e) {
                assertTrue("Error should be an AssertionError", e instanceof AssertionError);
            }
        }
    }
    
    /**
     * Test adding a view style name. To prove that a real message was send, we test for assertion error about missing scheduler (as we're in a test environment).
     */
    public final void testAddStyleName() {
        final Element element = DOM.createDiv();
        element.setId(SLOT_ID);
        RootPanel.getBodyElement().appendChild(element);
        dispatcher.attachDispatcherOnElement(element);
        registerDummyProxyInDispatcher(dispatcher);
        
        if (assertionsAreEnabled()) {
            try {
                proxy.addStyleName("test");
                fail("proxy didn't try to send a real proxy command");
            } catch (AssertionError e) {
                assertTrue("Error should be about missing scheduler", e.getMessage().contains("scheduler"));
            }
        }

        RootPanel.getBodyElement().removeChild(element);
    }
    
    /**
     * Test adding a view style name when no real view is attached. Nothing should happens, no real message should be sent.
     */
    public final void testAddStyleNameWithNoRealViewAttached() {
        assertFalse("Proxy should not be attached yet to a real view", proxy.isProxyAttachedToRealView());

        if (assertionsAreEnabled()) {
            try {
                proxy.addStyleName("test");
                assertTrue(true);
            } catch (AssertionError e) {
                fail("proxy did try to send a real proxy command");
            }
        }
    }
    
    /**
     * Test trying to add a null style name on the view . Should raise an assertion error.
     */
    public final void testAddStyleNameWithNullStyle() {
        if (assertionsAreEnabled()) {
            try {
                proxy.addStyleName(null);
                fail("OPViewProxy should raise an assertion error when adding a null style name.");
            } catch (AssertionError e) {
                assertTrue("Error should be an AssertionError", e instanceof AssertionError);
            }
        }
    }

    /**
     * Test removing a view style name. To prove that a real message was send, we test for assertion error about missing scheduler (as we're in a test environment).
     */
    public final void testRemoveStyleName() {
        final Element element = DOM.createDiv();
        element.setId(SLOT_ID);
        RootPanel.getBodyElement().appendChild(element);
        dispatcher.attachDispatcherOnElement(element);
        registerDummyProxyInDispatcher(dispatcher);
        
        if (assertionsAreEnabled()) {
            try {
                proxy.removeStyleName("test");
                fail("proxy didn't try to send a real proxy command");
            } catch (AssertionError e) {
                assertTrue("Error should be about missing scheduler", e.getMessage().contains("scheduler"));
            }
        }

        RootPanel.getBodyElement().removeChild(element);
    }
    
    /**
     * Test removing a view style name when no real view is attached. Nothing should happens, no real message should be sent.
     */
    public final void testRemoveStyleNameWithNoRealViewAttached() {
        assertFalse("Proxy should not be attached yet to a real view", proxy.isProxyAttachedToRealView());

        if (assertionsAreEnabled()) {
            try {
                proxy.removeStyleName("test");
                assertTrue(true);
            } catch (AssertionError e) {
                fail("proxy did try to send a real proxy command");
            }
        }
    }
    
    /**
     * Test trying to remove a null style name on the view . Should raise an assertion error.
     */
    public final void testRemoveStyleNameWithNullStyle() {
        if (assertionsAreEnabled()) {
            try {
                proxy.removeStyleName(null);
                fail("OPViewProxy should raise an assertion error when removing a null style name.");
            } catch (AssertionError e) {
                assertTrue("Error should be an AssertionError", e instanceof AssertionError);
            }
        }
    }
    
    /**
     * Test setting a view style primary name. To prove that a real message was send, we test for assertion error about missing scheduler (as we're in a test environment).
     */
    public final void testSetStylePrimaryName() {
        final Element element = DOM.createDiv();
        element.setId(SLOT_ID);
        RootPanel.getBodyElement().appendChild(element);
        dispatcher.attachDispatcherOnElement(element);
        registerDummyProxyInDispatcher(dispatcher);
        
        if (assertionsAreEnabled()) {
            try {
                proxy.setStylePrimaryName("test");
                fail("proxy didn't try to send a real proxy command");
            } catch (AssertionError e) {
                assertTrue("Error should be about missing scheduler", e.getMessage().contains("scheduler"));
            }
        }

        RootPanel.getBodyElement().removeChild(element);
    }
    
    /**
     * Test setting a view style primary name when no real view is attached. Nothing should happens, no real message should be sent.
     */
    public final void testSetStylePrimaryNameWithNoRealViewAttached() {
        assertFalse("Proxy should not be attached yet to a real view", proxy.isProxyAttachedToRealView());

        if (assertionsAreEnabled()) {
            try {
                proxy.setStylePrimaryName("test");
                assertTrue(true);
            } catch (AssertionError e) {
                fail("proxy did try to send a real proxy command");
            }
        }
    }
    
    /**
     * Test trying to set a null style primary name on the view. Should raise an assertion error.
     */
    public final void testSetStylePrimaryNameWithNullStyle() {
        if (assertionsAreEnabled()) {
            try {
                proxy.setStylePrimaryName(null);
                fail("OPViewProxy should raise an assertion error when setting a null style primary name.");
            } catch (AssertionError e) {
                assertTrue("Error should be an AssertionError", e instanceof AssertionError);
            }
        }
    }
    
    /**
     * Test adding a view style dependent name. To prove that a real message was send, we test for assertion error about missing scheduler (as we're in a test environment).
     */
    public final void testAddStyleDependentName() {
        final Element element = DOM.createDiv();
        element.setId(SLOT_ID);
        RootPanel.getBodyElement().appendChild(element);
        dispatcher.attachDispatcherOnElement(element);
        registerDummyProxyInDispatcher(dispatcher);
        
        if (assertionsAreEnabled()) {
            try {
                proxy.addStyleDependentName("test");
                fail("proxy didn't try to send a real proxy command");
            } catch (AssertionError e) {
                assertTrue("Error should be about missing scheduler", e.getMessage().contains("scheduler"));
            }
        }

        RootPanel.getBodyElement().removeChild(element);
    }
    
    /**
     * Test adding a view style dependent name when no real view is attached. Nothing should happens, no real message should be sent.
     */
    public final void testAddStyleDependentNameWithNoRealViewAttached() {
        assertFalse("Proxy should not be attached yet to a real view", proxy.isProxyAttachedToRealView());

        if (assertionsAreEnabled()) {
            try {
                proxy.addStyleDependentName("test");
                assertTrue(true);
            } catch (AssertionError e) {
                fail("proxy did try to send a real proxy command");
            }
        }
    }
    
    /**
     * Test trying to add a null style dependent name on the view. Should raise an assertion error.
     */
    public final void testAddStyleDependentNameWithNullStyle() {
        if (assertionsAreEnabled()) {
            try {
                proxy.addStyleDependentName(null);
                fail("OPViewProxy should raise an assertion error when adding a null style dependent name.");
            } catch (AssertionError e) {
                assertTrue("Error should be an AssertionError", e instanceof AssertionError);
            }
        }
    }

    /**
     * Test removing a view style dependent name. To prove that a real message was send, we test for assertion error about missing scheduler (as we're in a test environment).
     */
    public final void testRemoveStyleDependentName() {
        final Element element = DOM.createDiv();
        element.setId(SLOT_ID);
        RootPanel.getBodyElement().appendChild(element);
        dispatcher.attachDispatcherOnElement(element);
        registerDummyProxyInDispatcher(dispatcher);
        
        if (assertionsAreEnabled()) {
            try {
                proxy.removeStyleDependentName("test");
                fail("proxy didn't try to send a real proxy command");
            } catch (AssertionError e) {
                assertTrue("Error should be about missing scheduler", e.getMessage().contains("scheduler"));
            }
        }

        RootPanel.getBodyElement().removeChild(element);
    }
    
    /**
     * Test removing a view style dependent name when no real view is attached. Nothing should happens, no real message should be sent.
     */
    public final void testRemoveStyleDependentNameWithNoRealViewAttached() {
        assertFalse("Proxy should not be attached yet to a real view", proxy.isProxyAttachedToRealView());

        if (assertionsAreEnabled()) {
            try {
                proxy.removeStyleDependentName("test");
                assertTrue(true);
            } catch (AssertionError e) {
                fail("proxy did try to send a real proxy command");
            }
        }
    }
    
    /**
     * Test trying to remove a null style dependent name on the view. Should raise an assertion error.
     */
    public final void testRemoveStyleDependentNameWithNullStyle() {
        if (assertionsAreEnabled()) {
            try {
                proxy.removeStyleDependentName(null);
                fail("OPViewProxy should raise an assertion error when removing a null style dependent name.");
            } catch (AssertionError e) {
                assertTrue("Error should be an AssertionError", e instanceof AssertionError);
            }
        }
    }
    
    /**
     * Test setting a view width. To prove that a real message was send, we test for assertion error about missing scheduler (as we're in a test environment).
     */
    public final void testSetWidth() {
        final Element element = DOM.createDiv();
        element.setId(SLOT_ID);
        RootPanel.getBodyElement().appendChild(element);
        dispatcher.attachDispatcherOnElement(element);
        registerDummyProxyInDispatcher(dispatcher);
        
        if (assertionsAreEnabled()) {
            try {
                proxy.setWidth("10px");
                fail("proxy didn't try to send a real proxy command");
            } catch (AssertionError e) {
                assertTrue("Error should be about missing scheduler", e.getMessage().contains("scheduler"));
            }
        }

        RootPanel.getBodyElement().removeChild(element);
    }
    
    /**
     * Test setting a view width when no real view is attached. Nothing should happens, no real message should be sent.
     */
    public final void testSetWidthWithNoRealViewAttached() {
        assertFalse("Proxy should not be attached yet to a real view", proxy.isProxyAttachedToRealView());

        if (assertionsAreEnabled()) {
            try {
                proxy.setWidth("10px");
                assertTrue(true);
            } catch (AssertionError e) {
                fail("proxy did try to send a real proxy command");
            }
        }
    }
    
    /**
     * Test trying to set a null width on the view. Should raise an assertion error.
     */
    public final void testSetNullWidth() {
        if (assertionsAreEnabled()) {
            try {
                proxy.setWidth(null);
                fail("OPViewProxy should raise an assertion error when setting a null width.");
            } catch (AssertionError e) {
                assertTrue("Error should be an AssertionError", e instanceof AssertionError);
            }
        }
    }
    
    /**
     * Test setting a view height. To prove that a real message was send, we test for assertion error about missing scheduler (as we're in a test environment).
     */
    public final void testSetHeight() {
        final Element element = DOM.createDiv();
        element.setId(SLOT_ID);
        RootPanel.getBodyElement().appendChild(element);
        dispatcher.attachDispatcherOnElement(element);
        registerDummyProxyInDispatcher(dispatcher);
        
        if (assertionsAreEnabled()) {
            try {
                proxy.setHeight("10px");
                fail("proxy didn't try to send a real proxy command");
            } catch (AssertionError e) {
                assertTrue("Error should be about missing scheduler", e.getMessage().contains("scheduler"));
            }
        }

        RootPanel.getBodyElement().removeChild(element);
    }
    
    /**
     * Test setting a view height when no real view is attached. Nothing should happens, no real message should be sent.
     */
    public final void testSetHeightWithNoRealViewAttached() {
        assertFalse("Proxy should not be attached yet to a real view", proxy.isProxyAttachedToRealView());

        if (assertionsAreEnabled()) {
            try {
                proxy.setHeight("10px");
                assertTrue(true);
            } catch (AssertionError e) {
                fail("proxy did try to send a real proxy command");
            }
        }
    }
    
    /**
     * Test trying to set a null height on the view. Should raise an assertion error.
     */
    public final void testSetNullHeight() {
        if (assertionsAreEnabled()) {
            try {
                proxy.setHeight(null);
                fail("OPViewProxy should raise an assertion error when setting a null height.");
            } catch (AssertionError e) {
                assertTrue("Error should be an AssertionError", e instanceof AssertionError);
            }
        }
    }
    
    /**
     * Test setting a view size. To prove that a real message was send, we test for assertion error about missing scheduler (as we're in a test environment).
     */
    public final void testSetSize() {
        final Element element = DOM.createDiv();
        element.setId(SLOT_ID);
        RootPanel.getBodyElement().appendChild(element);
        dispatcher.attachDispatcherOnElement(element);
        registerDummyProxyInDispatcher(dispatcher);
        
        if (assertionsAreEnabled()) {
            try {
                proxy.setSize("10px", "20px");
                fail("proxy didn't try to send a real proxy command");
            } catch (AssertionError e) {
                assertTrue("Error should be about missing scheduler", e.getMessage().contains("scheduler"));
            }
        }

        RootPanel.getBodyElement().removeChild(element);
    }
    
    /**
     * Test setting a view size when no real view is attached. Nothing should happens, no real message should be sent.
     */
    public final void testSetSizeWithNoRealViewAttached() {
        assertFalse("Proxy should not be attached yet to a real view", proxy.isProxyAttachedToRealView());

        if (assertionsAreEnabled()) {
            try {
                proxy.setSize("10px", "20px");
                assertTrue(true);
            } catch (AssertionError e) {
                fail("proxy did try to send a real proxy command");
            }
        }
    }
    
    /**
     * Test trying to set a view size with a null width . Should raise an assertion error.
     */
    public final void testSetSizeWithNullWidth() {
        if (assertionsAreEnabled()) {
            try {
                proxy.setSize(null, "20px");
                fail("OPViewProxy should raise an assertion error when setting a null width.");
            } catch (AssertionError e) {
                assertTrue("Error should be an AssertionError", e instanceof AssertionError);
            }
        }
    }
    
    /**
     * Test trying to set a view size with a null height. Should raise an assertion error.
     */
    public final void testSetSizeWithNullHeight() {
        if (assertionsAreEnabled()) {
            try {
                proxy.setSize("10px", null);
                fail("OPViewProxy should raise an assertion error when setting a null height.");
            } catch (AssertionError e) {
                assertTrue("Error should be an AssertionError", e instanceof AssertionError);
            }
        }
    }

    /**
     * Test setting a view visibility. To prove that a real message was send, we test for assertion error about missing scheduler (as we're in a test environment).
     */
    public final void testSetVisible() {
        final Element element = DOM.createDiv();
        element.setId(SLOT_ID);
        RootPanel.getBodyElement().appendChild(element);
        dispatcher.attachDispatcherOnElement(element);
        registerDummyProxyInDispatcher(dispatcher);
        
        if (assertionsAreEnabled()) {
            try {
                proxy.setVisible(false);
                fail("proxy didn't try to send a real proxy command");
            } catch (AssertionError e) {
                assertTrue("Error should be about missing scheduler", e.getMessage().contains("scheduler"));
            }
        }

        RootPanel.getBodyElement().removeChild(element);
    }
    
    /**
     * Test setting a view visibility when no real view is attached. Nothing should happens, no real message should be sent.
     */
    public final void testSetVisibleWithNoRealViewAttached() {
        assertFalse("Proxy should not be attached yet to a real view", proxy.isProxyAttachedToRealView());

        if (assertionsAreEnabled()) {
            try {
                proxy.setVisible(false);
                assertTrue(true);
            } catch (AssertionError e) {
                fail("proxy did try to send a real proxy command");
            }
        }
    }
    
    /**
     * Dummy class implementing {@link OPMessageFromEmbeddedViewHandler}.
     */
    class DummyMessageFromEmbeddedViewHandler implements OPMessageFromEmbeddedViewHandler {

        public int counterOfTimeCalled = 0;
        public String message;
        public OPParams params;
        public int counterOfOnAttachCalled = 0;

        /**
         * Handle message from embedded view.
         * 
         * @see fr.openparts.OpenParts.client.OPMessageFromEmbeddedViewHandler#handleMessageFromEmbeddedView(java.lang.String,
         *      fr.openparts.OpenParts.client.OPParams)
         */
        @Override
        public void handleMessageFromEmbeddedView(final String message, final OPParams params) {
            ++counterOfTimeCalled;
            this.message = message;
            this.params = params;
        }

        /**
         * Called when the embedded view is attached.
         * 
         * @see fr.openparts.OpenParts.client.OPMessageFromEmbeddedViewHandler#onEmbeddedViewAttach()
         */
        @Override
        public void onEmbeddedViewAttach() {
            ++counterOfOnAttachCalled;
        }
    }
    
    /**
     * Register a dummy slot proxy in the dispatcher.
     * 
     * @param dispatcher
     *            the dispatcher on which to register the proxy.
     */
    private final native void registerDummyProxyInDispatcher(final OPMessagesDispatcher dispatcher) /*-{
        dispatcher.messageFromContainerSlotHandlerCallback = 1;
    }-*/;

    /**
     * Check if assertions are enabled.
     * 
     * @return true if assertions are enabled, false otherwise
     */
    private final boolean assertionsAreEnabled() {
        try {
            assert false;
            return false;
        } catch (AssertionError e) {
            return true;
        }
    }

}
